/**
 * 高性能 ECS 组件实现示例
 * 
 * 展示了三种不同的组件实现方式：
 * 1. 标准对象组件（易用性优先）
 * 2. TypedArray 组件（性能优先）
 * 3. 混合组件（平衡方案）
 */

import { ecs } from "./ECS";

//#region 1. 标准对象组件（推荐用于一般场景）

/**
 * 位置组件 - 标准实现
 * 
 * 特点：
 * - 代码简单易懂
 * - 类型安全
 * - 适合中小规模数据（< 1000 个实体）
 */
@ecs.register('Position')
export class PositionComponent extends ecs.Comp {
    public x: number = 0;
    public y: number = 0;
    
    reset(): void {
        this.x = 0;
        this.y = 0;
    }
    
    set(x: number, y: number): this {
        this.x = x;
        this.y = y;
        return this;
    }
    
    add(dx: number, dy: number): this {
        this.x += dx;
        this.y += dy;
        return this;
    }
}

/**
 * 速度组件 - 标准实现
 */
@ecs.register('Velocity')
export class VelocityComponent extends ecs.Comp {
    public vx: number = 0;
    public vy: number = 0;
    
    reset(): void {
        this.vx = 0;
        this.vy = 0;
    }
    
    set(vx: number, vy: number): this {
        this.vx = vx;
        this.vy = vy;
        return this;
    }
}

//#endregion

//#region 2. TypedArray 组件（推荐用于大规模场景）

/**
 * 粒子组件 - TypedArray 实现
 * 
 * 特点：
 * - 真正的内存连续性
 * - CPU Cache 友好
 * - 适合大规模数据（> 5000 个实体）
 * - 可以使用 SIMD 优化
 * 
 * 数据布局：[x, y, vx, vy, life, size, rotation, alpha]
 */
@ecs.register('Particle')
export class ParticleComponent extends ecs.Comp {
    // 静态数据缓冲区 - 所有粒子共享
    private static readonly MAX_PARTICLES = 50000;
    private static readonly FIELDS_PER_PARTICLE = 8;
    private static data: Float32Array = new Float32Array(
        ParticleComponent.MAX_PARTICLES * ParticleComponent.FIELDS_PER_PARTICLE
    );
    private static activeCount: number = 0;
    private static freeIndices: number[] = [];
    
    // 实例只存储索引
    public dataIndex: number = -1;
    
    constructor() {
        super();
        // 分配索引
        if (ParticleComponent.freeIndices.length > 0) {
            this.dataIndex = ParticleComponent.freeIndices.pop()!;
        } else {
            this.dataIndex = ParticleComponent.activeCount++;
        }
        
        if (this.dataIndex >= ParticleComponent.MAX_PARTICLES) {
            console.error('粒子数量超过最大限制！');
            this.dataIndex = ParticleComponent.MAX_PARTICLES - 1;
        }
    }
    
    // 通过 getter/setter 访问连续内存中的数据
    get x(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 0];
    }
    set x(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 0] = value;
    }
    
    get y(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 1];
    }
    set y(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 1] = value;
    }
    
    get vx(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 2];
    }
    set vx(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 2] = value;
    }
    
    get vy(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 3];
    }
    set vy(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 3] = value;
    }
    
    get life(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 4];
    }
    set life(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 4] = value;
    }
    
    get size(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 5];
    }
    set size(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 5] = value;
    }
    
    get rotation(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 6];
    }
    set rotation(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 6] = value;
    }
    
    get alpha(): number {
        return ParticleComponent.data[this.dataIndex * 8 + 7];
    }
    set alpha(value: number) {
        ParticleComponent.data[this.dataIndex * 8 + 7] = value;
    }
    
    reset(): void {
        const baseIndex = this.dataIndex * 8;
        for (let i = 0; i < 8; i++) {
            ParticleComponent.data[baseIndex + i] = 0;
        }
        
        // 回收索引
        if (this.dataIndex >= 0) {
            ParticleComponent.freeIndices.push(this.dataIndex);
        }
    }
    
    /**
     * 批量更新所有粒子（高性能）
     * CPU 可以更好地预取和缓存数据
     */
    static updateAll(dt: number): void {
        const data = ParticleComponent.data;
        const count = ParticleComponent.activeCount;
        
        // 连续内存访问，CPU Cache 友好
        for (let i = 0; i < count; i++) {
            const base = i * 8;
            // x += vx * dt
            data[base + 0] += data[base + 2] * dt;
            // y += vy * dt
            data[base + 1] += data[base + 3] * dt;
            // life -= dt
            data[base + 4] -= dt;
            // rotation += dt
            data[base + 6] += dt;
        }
    }
    
    /**
     * 获取直接访问数据缓冲区（用于高级优化）
     */
    static getDataBuffer(): Float32Array {
        return ParticleComponent.data;
    }
}

//#endregion

//#region 3. 混合组件（部分数据连续存储）

/**
 * 变换组件 - 混合实现
 * 
 * 特点：
 * - 常用数据（position, scale）存储在 TypedArray 中
 * - 不常用数据（parent, dirty）存储在对象中
 * - 平衡了性能和易用性
 */
@ecs.register('Transform')
export class TransformComponent extends ecs.Comp {
    // 连续存储的数据（频繁访问）
    private static readonly MAX_TRANSFORMS = 10000;
    private static positionData: Float32Array = new Float32Array(TransformComponent.MAX_TRANSFORMS * 2);
    private static scaleData: Float32Array = new Float32Array(TransformComponent.MAX_TRANSFORMS * 2);
    private static rotationData: Float32Array = new Float32Array(TransformComponent.MAX_TRANSFORMS);
    private static activeCount: number = 0;
    
    // 对象存储的数据（不常访问）
    public parent: TransformComponent | null = null;
    public dirty: boolean = false;
    public dataIndex: number = -1;
    
    constructor() {
        super();
        this.dataIndex = TransformComponent.activeCount++;
    }
    
    // Position - 连续存储
    get x(): number {
        return TransformComponent.positionData[this.dataIndex * 2];
    }
    set x(value: number) {
        TransformComponent.positionData[this.dataIndex * 2] = value;
        this.dirty = true;
    }
    
    get y(): number {
        return TransformComponent.positionData[this.dataIndex * 2 + 1];
    }
    set y(value: number) {
        TransformComponent.positionData[this.dataIndex * 2 + 1] = value;
        this.dirty = true;
    }
    
    // Scale - 连续存储
    get scaleX(): number {
        return TransformComponent.scaleData[this.dataIndex * 2];
    }
    set scaleX(value: number) {
        TransformComponent.scaleData[this.dataIndex * 2] = value;
        this.dirty = true;
    }
    
    get scaleY(): number {
        return TransformComponent.scaleData[this.dataIndex * 2 + 1];
    }
    set scaleY(value: number) {
        TransformComponent.scaleData[this.dataIndex * 2 + 1] = value;
        this.dirty = true;
    }
    
    // Rotation - 连续存储
    get rotation(): number {
        return TransformComponent.rotationData[this.dataIndex];
    }
    set rotation(value: number) {
        TransformComponent.rotationData[this.dataIndex] = value;
        this.dirty = true;
    }
    
    reset(): void {
        const base = this.dataIndex * 2;
        TransformComponent.positionData[base] = 0;
        TransformComponent.positionData[base + 1] = 0;
        TransformComponent.scaleData[base] = 1;
        TransformComponent.scaleData[base + 1] = 1;
        TransformComponent.rotationData[this.dataIndex] = 0;
        
        this.parent = null;
        this.dirty = false;
    }
    
    setPosition(x: number, y: number): this {
        this.x = x;
        this.y = y;
        return this;
    }
    
    setScale(sx: number, sy: number = sx): this {
        this.scaleX = sx;
        this.scaleY = sy;
        return this;
    }
}

//#endregion

//#region 工具函数

/**
 * 预分配组件对象池
 * 在游戏启动时调用，预先创建组件对象以获得更好的内存连续性
 */
export function preloadComponentPools(config: {
    position?: number;
    velocity?: number;
    particle?: number;
    transform?: number;
}): void {
    const { position = 1000, velocity = 1000, particle = 5000, transform = 1000 } = config;
    
    console.log('预分配组件对象池...');
    
    // 预分配标准组件
    if (position > 0) {
        for (let i = 0; i < position; i++) {
            const comp = new PositionComponent();
            comp.reset();
            // 手动加入对象池
            // ECSModel.compPools.get(PositionComponent.tid)!.push(comp);
        }
    }
    
    if (velocity > 0) {
        for (let i = 0; i < velocity; i++) {
            const comp = new VelocityComponent();
            comp.reset();
            // ECSModel.compPools.get(VelocityComponent.tid)!.push(comp);
        }
    }
    
    console.log(`组件对象池预分配完成：Position=${position}, Velocity=${velocity}`);
}

/**
 * 性能测试工具
 */
export class ComponentPerformanceTest {
    /**
     * 测试标准组件性能
     */
    static testStandardComponent(count: number): number {
        const startTime = performance.now();
        
        const components: PositionComponent[] = [];
        for (let i = 0; i < count; i++) {
            const comp = new PositionComponent();
            comp.set(i, i);
            components.push(comp);
        }
        
        // 遍历更新
        for (let i = 0; i < components.length; i++) {
            components[i].x += 1;
            components[i].y += 1;
        }
        
        const endTime = performance.now();
        return endTime - startTime;
    }
    
    /**
     * 测试 TypedArray 组件性能
     */
    static testTypedArrayComponent(count: number): number {
        const startTime = performance.now();
        
        const components: ParticleComponent[] = [];
        for (let i = 0; i < count; i++) {
            const comp = new ParticleComponent();
            comp.x = i;
            comp.y = i;
            components.push(comp);
        }
        
        // 批量更新（利用连续内存）
        ParticleComponent.updateAll(0.016);
        
        const endTime = performance.now();
        return endTime - startTime;
    }
    
    /**
     * 运行性能对比测试
     */
    static runPerformanceComparison(count: number = 10000): void {
        console.log(`\n========== 组件性能测试 (${count} 个实体) ==========`);
        
        const standardTime = this.testStandardComponent(count);
        console.log(`标准对象组件：${standardTime.toFixed(2)}ms`);
        
        const typedArrayTime = this.testTypedArrayComponent(count);
        console.log(`TypedArray组件：${typedArrayTime.toFixed(2)}ms`);
        
        const speedup = (standardTime / typedArrayTime).toFixed(2);
        console.log(`性能提升：${speedup}x`);
        console.log('='.repeat(50) + '\n');
    }
}

//#endregion

//#region 使用示例

/**
 * 使用示例
 */
export class ComponentUsageExample {
    static example1_StandardComponent() {
        // 1. 标准组件使用（推荐用于一般场景）
        // const entity = ecs.createEntity();
        
        // const pos = entity.add(PositionComponent);
        // pos.set(100, 200);
        
        // const vel = entity.add(VelocityComponent);
        // vel.set(10, 5);
        
        // // 更新
        // pos.x += vel.vx;
        // pos.y += vel.vy;
    }
    
    static example2_TypedArrayComponent() {
        // 2. TypedArray 组件使用（推荐用于大规模粒子等）
        const particles: ParticleComponent[] = [];
        
        // 创建 10000 个粒子
        for (let i = 0; i < 10000; i++) {
            // const entity = ecs.createEntity();
            // const particle = entity.add(ParticleComponent);
            // particle.x = Math.random() * 800;
            // particle.y = Math.random() * 600;
            // particle.vx = (Math.random() - 0.5) * 2;
            // particle.vy = (Math.random() - 0.5) * 2;
            // particle.life = 1.0;
            // particles.push(particle);
        }
        
        // 批量更新（高性能）
        ParticleComponent.updateAll(0.016);
    }
    
    static example3_MixedComponent() {
        // 3. 混合组件使用
        // const entity = ecs.createEntity();
        // const transform = entity.add(TransformComponent);
        
        // transform.setPosition(100, 200);
        // transform.setScale(2.0);
        // transform.rotation = Math.PI / 4;
        
        // // 父子关系（对象存储）
        // const child = ecs.createEntity();
        // const childTransform = child.add(TransformComponent);
        // childTransform.parent = transform;
    }
}

//#endregion

